
#include "user_manager.h"

#include <iostream>
#include "session.h"

int user_manager::user_login(std::shared_ptr<session> session_ptr,
    const std::string &name, const std::string &password, uint32_t &uid)
{
    int ret = NET_EC_OK;
    mysqlx::RowResult res = table_.select("uid", "uname", "passwd")
                                    .where("uname = :param")
                                    .bind("param", name)
                                    .execute();
    
    if (res.count() == 0) {
        std::cout << "user not found, uname: " << name << std::endl;
        return NET_EC_NOT_FOUND;
    }

    if (res.count() > 1) {
        std::cout << "duplicate user, uname: " << name << std::endl;
        return NET_EC_DUPLICATE;
    }

    mysqlx::Row row = res.fetchOne();

    if (row[2].get<std::string>() != password) {
        std::cout << "password error, uname: " << name << std::endl;
        return NET_EC_PASSWORD_ERROR;
    }

    uid = row[0].get<uint32_t>();

    /* 创建一个user类的对象，并存放到全局软表中 */
    std::shared_ptr<user> user_ptr = std::make_shared<user>(name, uid);
    online_users_[uid] = user_ptr;
    user_ptr->set_session(session_ptr);
    user_ptr->set_status(user::status_t::ONLINE);

    /* 建立session和user的双向映射关系 */
    session_user_map_[session_ptr] = user_ptr;
    user_session_map_[user_ptr] = session_ptr;
    return ret;
}

int user_manager::user_logout(uint32_t uid)
{
    int ret = NET_EC_OK;
    if (online_users_.find(uid) == online_users_.end()) {
        printf("user not found, uid = %d\n", uid);
        return NET_EC_NOT_FOUND;
    }
    std::shared_ptr<user> user = online_users_[uid];

    if (user->status() == user::status_t::OFFLINE) {
        printf("user not online, uid = %d\n", uid);
        return NET_EC_INVALID_STATE;
    } else if (user->status() == user::status_t::GAMING) {
        /* TODO: */
        return NET_EC_NOT_SUPPORT;
    } else {
        user->set_status(user::status_t::OFFLINE);
        online_users_.erase(uid);
    }

    return ret;
}

int user_manager::user_signup(const std::string &name, const std::string &password, uint32_t &uid)
{
    int ret = NET_EC_OK;
    mysqlx::RowResult res = table_.select("uid", "uname", "passwd")
                                    .where("uname = :param")
                                    .bind("param", name)
                                    .execute();
    
    if (res.count() != 0) {
        std::cout << "user name already exist" << name << std::endl;
        return NET_EC_ALREADY_EXIST;
    }

    mysqlx::Result insert_res = table_.insert("uname", "passwd")
       .values(name, password)
       .execute();
    if (insert_res.getAffectedItemsCount() != 1) {
        std::cout << "insert user info failed, uname: " << name << std::endl;
        return NET_EC_DB_ERROR;
    }

    /* 插入数据后重新查询 */
    res = table_.select("uid", "uname", "passwd")
                        .where("uname = :param")
                        .bind("param", name)
                        .execute();
    if (res.count() != 1) {
        std::cout << "insert user info failed, uname: " << name << std::endl;
        return NET_EC_DB_ERROR;
    }

    mysqlx::Row row = res.fetchOne();            
    uid = row[0].get<uint32_t>();
    return ret;
}

int user_manager::user_delete_account(uint32_t uid)
{
    int ret = NET_EC_OK;
    mysqlx::Result res = table_.remove().where("uid = :param").bind("param", uid).execute();
    if (res.getAffectedItemsCount() != 1) {
        std::cout << "insert user info failed, uid: " << uid << std::endl;
        return NET_EC_DB_ERROR;
    }

    return ret;
}

int user_manager::user_delete_account(const std::string &name)
{
    int ret = NET_EC_OK;
    mysqlx::Result res = table_.remove().where("uname = :param").bind("param", name).execute();
    if (res.getAffectedItemsCount() != 1) {
        std::cout << "delete user failed, uname: " << name << std::endl;
        return NET_EC_DB_ERROR;
    }

    return ret;
}
